﻿using System;
using System.Collections.Generic;
using IQIGame.Onigao.Framework;
using IQIGame.Onigao.Game;
using NetProtocol.Client;
using NetProtocol.POD;

namespace IQIGame.Onigao.GamePlay
{
    public class PetModule : Singleton<PetModule>, CNetPet
    {
        private PetModule() { }

        private PetModuleData petData => GameDataCenter.PlayerData.pet;

        public void InitModule(PlayerPOD playerPOD)
        {
            PetModuleData data = new PetModuleData(playerPOD.petBagCapacity);
            GameDataCenter.PlayerData.pet = data;
            foreach (var pod in playerPOD.pets)
            {
                this.UpdateOrNewPet(pod);
            }
        }

        public void ClearModule()
        {
            var petData = GameDataCenter.PlayerData.pet;
            GameDataCenter.PlayerData.pet = null;
            petData?.Clear();
        }


        #region Net层

        static public CNetPet NetCore => Instance;

        ISession CNetPet.GetSession()
        {
            return GameServerModule.Instance.CurrSession;
        }

        void CNetPet.SC_notifyPetActive(ISession session, PetPOD petPOD)
        {
            this.UpdateOrNewPet(petPOD);
        }

        void CNetPet.SC_notifyPetBagCapacity(ISession session, int capacity)
        {
            petData.UpdateBagCapacity(capacity);
        }

        void CNetPet.SC_notifyPetRemove(ISession session, List<long> removeList)
        {
            foreach (var id in removeList)
            {
                petData.Remove(id);
            }
        }
        #endregion

        public void UpdateOrNewPet(PetPOD pod)
        {
            if (petData.TryGetValue(pod.id, out Pet pet))
            {
                pet.Sync(pod);
            }
            else
            {
                pet = Pet.ConvertBy(pod);
                petData.Put(pet);
            }
            PODPool<PetPOD>.Put(pod);
        }

        public List<Pet> LeachList(List<Pet> orgList, PetFilter filter, List<Pet> destList = null)
        {
            if (destList == null)
                destList = new List<Pet>(16);
            bool isDefault = filter == PetFilter.Default;
            foreach (var item in orgList)
            {
                bool isCanAdd = isDefault || this.IsCanAddData(item, filter);
                if (isCanAdd)
                {
                    destList.Add(item);
                }
            }
            return destList;
        }

        private bool IsCanAddData(Pet pet, PetFilter filter)
        {
            bool isCanAdd = IsCanAddTypeState(pet, filter) && IsCanAddLockState(pet, filter);
            return isCanAdd && IsCanAddWearState(pet, filter);
        }

        private bool IsCanAddTypeState(Pet pet, PetFilter filter)
        {
            return (filter.orgType == 0) || ((int)pet.cfgData.Type == filter.orgType);
        }

        private bool IsCanAddLockState(Pet pet, PetFilter filter)
        {
            if (filter.lockState == 0)
                return true;
            if (filter.lockState == 1)
                return pet.isLock;
            return !pet.isLock;
        }

        private bool IsCanAddWearState(Pet pet, PetFilter filter)
        {
            if (filter.wearState == 0)
                return true;
            bool isWear = filter.wearState == 1;
            var wearer = pet.currWearer;
            if (isWear)
            {
                return wearer != null;
            }
            return wearer == null;
        }

        public void ReorderList(List<Pet> list, PetSort sort, Func<Pet, Pet, int> funcOutSort = null)
        {
            int cnt = list?.Count ?? 0;
            if (cnt <= 1)
                return;
            var _sortFunc = this.MakeSortFunc(sort, funcOutSort);
            list.Sort(_sortFunc);
        }

        private System.Comparison<Pet> MakeSortFunc(PetSort sort, Func<Pet, Pet, int> funcOutSort = null)
        {
            return (Pet a, Pet b) =>
            {
                if (funcOutSort != null)
                {
                    int valOutSort = funcOutSort(a, b);
                    if (valOutSort != 0)
                    {
                        return valOutSort;
                    }
                }
                long sortA = 0;
                long sortB = 0;
                PetSortType sortType = (PetSortType)sort.sortType;
                switch (sortType)
                {
                    case PetSortType.CreateTime:
                        sortA = a.createTime;
                        sortB = b.createTime;
                        break;
                    case PetSortType.Type:
                        sortA = (int)a.cfgData.Type;
                        sortB = (int)b.cfgData.Type;
                        break;
                    default:
                        sortA = (int)a.level;
                        sortB = (int)b.level;
                        break;
                }
                if (sortA == sortB)
                {
                    sortA = a.cfgData.Id;
                    sortB = b.cfgData.Id;
                    if (sortA == sortB)
                    {
                        sortA = a.id;
                        sortB = b.id;
                    }
                }
                int symbol = sort.isDesc ? -1 : 1;
                return sortA > sortB ? 1 * symbol : -1 * symbol;
            };
        }

        public UIPetSlotType GetPabilityAttributeSlotType(Pet pet, int pabilityAttributeCid)
        {
            if (pet.ContainsUsingPabilityAttribute(pabilityAttributeCid))
            {
                return UIPetSlotType.Used;
            }
            int groupIndex = pet.GetPabilityGroupIndex(pabilityAttributeCid);
            if (groupIndex == -1)
            {
                return UIPetSlotType.LockByLv;
            }
            var pabilityUnlockLv = pet.cfgData.RandomPabilityUnlockLv[groupIndex];
            return (pabilityUnlockLv > pet.level) ? UIPetSlotType.LockByLv : UIPetSlotType.Unlock;
        }
    }
}
